package com.example.demo.config;

import com.example.demo.service.ILocalRateLimiter;
import com.example.demo.util.ApplicationContextUtil;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.support.WebApplicationContextUtils;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 本地内存限流配置
 *
 * @author zxb
 **/
@Configuration
public class LocalRateLimitConfig {

    /**
     * 配置例子：
     * spring.cloud.gateway.local-rate-limiter.config.localRateLimiterResolver=localIpRateLimitSimpleImpl
     * spring.cloud.gateway.local-rate-limiter.config.permitsPerSecond=10
     */
    @ConditionalOnProperty(
            value = "spring.cloud.gateway.local-rate-limiter.config"
    )
    @ConfigurationProperties(
            value = "spring.cloud.gateway.local-rate-limiter.config"
    )
    @EnableConfigurationProperties(value = LocalRateLimitConfig.class)
    @Configuration
    @Accessors(chain = true)
    @Data
    public static class LocalRateLimitProperties {
        /**
         * 限流 bean 的名称，配置使用哪一个 bean 去限流
         */
        private String localRateLimiterResolver;

        /**
         * 每秒令牌数目
         */
        private Double permitsPerSecond;

        /**
         * 扩展配置
         */
        private Map<String, Object> extend;

        public ILocalRateLimiter getLocalRateLimiter() {
            // fixme
            return (ILocalRateLimiter) ApplicationContextUtil.getBean(localRateLimiterResolver);
        }
    }

    /**
     * 默认配置
     * 1. 默认使用 ip 进行限流
     * 2. 默认令牌桶个数 20 个，30 分钟过期
     *
     * @return
     */
    @Bean
    @ConditionalOnMissingBean(value = LocalRateLimitProperties.class)
    public LocalRateLimitProperties localRateLimitProperties() {
        return new LocalRateLimitProperties()
                .setLocalRateLimiterResolver(Constants.IP_BEAN_NAME)
                // 30 分钟（60s * 30）
                .setExtend(Map.of(Constants.IP_EXPIRE_AFTER_ACCESS_FIELD_NAME, TimeUnit.MINUTES.toSeconds(30)))
                .setPermitsPerSecond(20.);
    }

    /**
     * 限流配置常量
     */
    public interface Constants {
        /**
         * ip 限流实现类
         */
        String IP_BEAN_NAME = "localIpRateLimitSimpleImpl";

        /**
         * ip 限流过期扩展字段
         */
        String IP_EXPIRE_AFTER_ACCESS_FIELD_NAME = "expireAfterAccess";
    }
}